package cc.facesign.admin.controller;

import cc.facesign.admin.bean.TblConf;
import cc.facesign.admin.bean.TblConfUser;
import cc.facesign.admin.bean.vo.ConfCreateVo;
import cc.facesign.admin.enums.ConfStatusType;
import cc.facesign.admin.service.*;
import cc.facesign.admin.utils.PowerUtils;
import cc.facesign.common.exception.FacesignException;
import cc.facesign.common.type.RoleType;
import cc.facesign.common.utils.bean.R;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 会议管理相关
 */
@RestController
@RequestMapping("/admin/conf")
@Api(description = "会议管理")
public class ConfManageController {

    @Autowired
    private TblConfService confService;

    @Autowired
    private TblUserService userService;

    @Autowired
    private TblConfUserService confUserService;

    @Autowired
    private PowerUtils powerUtils;

    @Autowired
    private TblDeptService deptService;

    @Autowired
    private AclService aclService;

    /**
     * 删除会议
     * @param id 会议id
     * @return
     */
    @PreAuthorize("@ex.hasAuthorith('root:exe:conf')")
    @ApiOperation("删除会议")
    @DeleteMapping("/deleteById/{id}")
    public R deleteById(@PathVariable String id) {
        if(!powerUtils.getCurrentChildConfIdSet().contains(id)) {
            throw new FacesignException(R.ERROR, "权限异常或不存在");
        }

        HashSet<String> set = powerUtils.getCurrentChildConfIdSet();
        if (!set.contains(id) && !powerUtils.isConfCreater(id)) throw new FacesignException(R.ERROR, "权限非法");

        String createrId = confService.getById(id).getCreaterId();
        String rid = deptService.getRid(confService.getById(id).getDeptId());

        aclService.deleteManage(createrId, rid, "conf");

        confService.removeConfById(id);
        return R.ok();
    }

    /**
     * 拥有该会议管理权限可用
     * @param confId 会议id
     * @param userId 用户id
     * @return
     */
    @PreAuthorize("@ex.hasAuthorith('root:exe:conf')")
    @ApiOperation("修改会议创建者")
    @GetMapping("/editConfCreaterById")
    public R updateConfCreaterById(String confId,String userId) {
        //  不具备会议所在部门的管理权限且不是会议创建者
        if(!powerUtils.getCurrentChildConfIdSet().contains(confId) && !powerUtils.isConfCreater(confId)) {
            throw new FacesignException(R.ERROR, "权限异常");
        }

        if (confService.getById(confId) == null || userService.getById(userId) == null) {
            throw new FacesignException(R.ERROR, "无信息");
        }

        String createrId = confService.getById(confId).getCreaterId();

        // 更新
        TblConf conf = new TblConf();
        conf.setId(confId);
        conf.setCreaterId(userId);
        confService.updateById(conf);

        // 新会议创建者加入会议
        confUserService.relateBatch(Collections.singletonList(new TblConfUser(confId, userId)));

        // acl权限
        String rid = deptService.getRid(confService.getById(confId).getDeptId());
        aclService.setManage(userId, rid, RoleType.CONF);
        aclService.deleteManage(createrId, rid, RoleType.CONF);

        return R.ok();
    }

    /**
     * 修改会议状态
     * 需拥有会议管理权限，需满足以下条件：
     *      1、部门管理员可修改为所有status值（依据会议所在部门）
     *      2、仅有会议管理权限
     *          1、status值可从1（已通过）修改到3、4
     *          2、status值可从3->4或4->3
 *          3、会议修改为“审核未通过”或“已结束”，则更新用户的会议管理权限
     * @param confId 会议id
     * @param status 状态值
     */
    @PreAuthorize("@ex.hasAuthorith('root:exe:conf')")
    @ApiOperation("修改会议状态")
    @PutMapping("/updateStatus/{confId}/{status}")
    public R updateStatus(@PathVariable("confId") String confId,
                          @PathVariable("status") String status) {
        if (!powerUtils.getCurrentChildConfIdSet().contains(confId)) {
            throw new FacesignException(R.ERROR, "权限异常");
        }

        int statusInt = Integer.parseInt(status);

        // 校验值的合法性
        ConfStatusType.codeOf(statusInt);

        TblConf conf = confService.getById(confId);


        // 若仅有会议管理权限
        if (!powerUtils.getCurrentChildDeptIdSet().contains(conf.getDeptId())) {
            boolean flag = false;
            if (conf.getStatus() == 1 && (statusInt == 3 || statusInt ==4)) flag = true;
            if ((conf.getStatus() == 3 && statusInt == 4) || (conf.getStatus() == 4 && statusInt == 3)) flag = true;
            if (!flag) return R.error().message("非管理员不允许此操作");
        }

        conf.setStatus(statusInt);
        confService.updateById(conf);

        // 会议修改为“审核未通过”或“已结束”，则更新用户的会议管理权限
        if (statusInt == 2 || statusInt == 4) {
            aclService.deleteManage(conf.getCreaterId(), deptService.getRid(conf.getDeptId()), RoleType.CONF);
        }

        return R.ok();
    }


    /**
     * 拥有会议管理权限可以修改
     * 必须传入会议id
     *  该操作可修改：
     *      title、place、description、startTime
     * 日期格式 yyyy-MM-dd hh:mm
     * @return
     */
    @PreAuthorize("@ex.hasAuthorith('root:exe:conf')")
    @ApiOperation("编辑会议信息")
    @PostMapping("/editConfInfo")
    public R editConfInfo(@RequestBody Map<String, String> map) {
        String confId = map.get("id");
        String title = map.get("title");
        String place = map.get("place");
        String description = map.get("description");
        String startTime = map.get("startTime");

        TblConf conf;
        if (StringUtils.isEmpty(confId) || ( conf = confService.getById(confId)) == null) {
            return R.error().message("参数异常");
        }

        if (!powerUtils.getCurrentChildConfIdSet().contains(confId)) {
            return R.error().message("权限异常");
        }

        if (!StringUtils.isEmpty(title)) conf.setTitle(title);
        if (!StringUtils.isEmpty(place)) conf.setPlace(place);
        if (!StringUtils.isEmpty(description)) conf.setDescription(description);
        if (!StringUtils.isEmpty(startTime)) {
            DateTime date = DateUtil.parse(startTime, "yyyy-MM-dd HH:mm");
            conf.setStartTime(date);
        }

        confService.updateById(conf);

        return R.ok();
    }

    /**
     * 向会议中添加用户
     *  1. 通过用户id添加
     *  2. 只能会议创建者使用该方法
     *  3. 不会重复添加
     *  4. ids中不能有上级
     *
     * @param confId 会议id
     * @param ids 用户id list
     * @return 会议用户 simple信息
     */
    @PreAuthorize("@ex.hasAuthorith('root:exe:conf')")
    @ApiOperation("向会议中添加用户")
    @PostMapping("/addUsersForInfo")
    public R addUsersForInfo(String confId, @RequestParam List<String> ids) {
        Set<String> set = userService.getChildIdsByDeptId(powerUtils.getCurrentDeptId());
        if (!powerUtils.isConfCreater(confId) && !set.containsAll(ids)) {
            // 如果有ids中有上级，并且自身不是会议创建者
            return R.error().message("权限异常");
        }

        confService.addUserByIds(confId, ids);
        confService.updateTotal(confId);

        return R.ok();
    }

    /**
     * 创建会议
     * 1. title 和 deptId不能为空
     * 2. 若当前用户拥有deptId部门的管理权限，则创建的会议无需再审核，status为1，否则为0
     *
     * @param vo cc.facesign.admin.bean.vo.ConfCreateVo
     * @return
     */
    @ApiOperation("创建会议")
    @PostMapping("/createConf")
    public R createConf(@RequestBody ConfCreateVo vo) {

        String title = vo.getTitle();
        String place = vo.getPlace();
        String deptId = vo.getDeptId();
        String description = vo.getDescription();
        Date startTime = vo.getStartTime();
        if (StringUtils.isEmpty(title) || StringUtils.isEmpty(deptId)) {
            return R.error().message("数据错误");
        }

        TblConf conf = new TblConf();
        conf.setTitle(title);
        conf.setDeptId(deptId);
        if (!StringUtils.isEmpty(place)) conf.setPlace(place);
        if (!StringUtils.isEmpty(description)) conf.setDescription(description);
        if (startTime != null) conf.setStartTime(startTime);
        conf.setTotal(1);

        // 若拥有管理权限，则创建的会议无需审核
        if (powerUtils.getCurrentChildDeptIdSet().contains(deptId)) {
            conf.setStatus(1);
        }

        // 生成会议码
        String code = confService.createCode();
        conf.setCode(code);

        // 创建者为当前用户
        String userId = powerUtils.getCurrentUser().getId();
        conf.setCreaterId(userId);

        // 设置acl会议权限
        aclService.setManage(userId, deptService.getRid(deptId), RoleType.CONF);

        confService.save(conf);

        // 当前用户默认加入会议
        confService.addUserByIds(conf.getId(), Collections.singletonList(userId));

        return R.ok();
    }

    /**
     * 只有会议创建者和管理员可以删除
     * 如果删除的用户中包含会议创建者，则不能这样删除，可以直接删除会议
     * @param confId 会议id
     * @param ids 用户id
     * @return
     */
    @PreAuthorize("@ex.hasAuthorith('root:exe:conf')")
    @ApiOperation("会议中删除用户")
    @DeleteMapping("/deleteUsers/{confId}")
    public R deleteUsers(@PathVariable String confId,
                         @RequestBody List<String> ids) {
        if (!powerUtils.isAdmin() && !powerUtils.getCurrentChildConfIdSet().contains(confId)) {
            throw new FacesignException(R.ERROR, "权限异常");
        }

        // 包含创建者,不能删
        TblConf conf = confService.getById(confId);
        if (ids.contains(conf.getCreaterId())) {
            throw new FacesignException(R.ERROR, "错误");
        }

        confService.removeUsers(confId, ids);

        return R.ok();
    }
}
